package com.radar.example;

import cn.hutool.core.io.FileUtil;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import com.radar.algorithm.*;
import com.radar.common.*;
import com.radar.exception.RadarCaclError;
import com.radar.exception.RadarDecodeError;
import com.radar.exception.RadarVisualizeError;
import com.radar.io.CinradRadar;
import com.radar.io.RadarGridData;
import com.radar.utils.RefObj;
import com.radar.visualize.RasterMap;
import org.bytedeco.javacpp.indexer.Indexer;
import org.bytedeco.opencv.global.opencv_imgcodecs;
import org.bytedeco.opencv.global.opencv_imgproc;
import org.bytedeco.opencv.opencv_core.Mat;
import org.junit.Test;
import org.meteoinfo.data.GridData;
import org.meteoinfo.global.Extent;
import ucar.ma2.InvalidRangeException;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.List;

public class IoExample {

    static Log log = LogFactory.get();

    /**
     * 读取SA SB 波段雷达
     *
     * @throws RadarDecodeError
     * @throws IOException
     * @throws InvalidRangeException
     */
    @Test
    public void readSASB() throws RadarDecodeError, IOException, InvalidRangeException, RadarCaclError {
        long time = System.currentTimeMillis();
        String file = "F:\\data\\雷达\\短临雷达数据\\原始数据\\Z9090\\Z_RADR_I_Z9090_20190729235500_O_DOR_SB_CAP.bin";
        CinradRadar cinradRadar = new CinradRadar();
        cinradRadar.parse(file);
        log.info("radar site : {}", cinradRadar.radar.getRadarSite().toString());
        log.info("radar station code : {}", cinradRadar.code);
        log.info("cinrad radar type : {}", cinradRadar.type.name());
        log.info("radar ref resolution : {}m", cinradRadar.radar.getResolution(ProductType.REF));
        log.info("radar vel resolution : {}m", cinradRadar.radar.getResolution(ProductType.VEL));
        // 如果要保存netcdf 则需要调用该方法 否则只用netcdf 的数据结构 以及cache
        cinradRadar.radar.getCR();
        cinradRadar.radar.getET();
        cinradRadar.radar.getVIL();
        cinradRadar.radar.flush();
//        log.info(cinradRadar.radar.netcdf.getDetailInfo());
        // 必须调用该方法 否则nc tmp 文件一直保留
//        cinradRadar.dispose();
        log.info("sum time : {}", System.currentTimeMillis() - time);
    }

    /**
     * 读取CA CB 波段雷达
     *
     * @throws RadarDecodeError
     * @throws IOException
     * @throws InvalidRangeException
     */
    @Test
    public void readCACB() throws RadarDecodeError, IOException, InvalidRangeException {
        long time = System.currentTimeMillis();
        String file = "/Users/xx/data/micaps/SINGLERADAR/ARCHIVES/PRE_QC/Z9836/Z_RADR_I_Z9836_20190730001000_O_DOR_CA_CAP.bin.bz2";
        CinradRadar cinradRadar = new CinradRadar();
        cinradRadar.parse(file);
        log.info("radar site : {}", cinradRadar.radar.getRadarSite().toString());
        log.info("radar station code : {}", cinradRadar.code);
        log.info("cinrad radar type : {}", cinradRadar.type.name());
        log.info("radar ref resolution : {}m", cinradRadar.radar.getResolution(ProductType.REF));
        log.info("radar vel resolution : {}m", cinradRadar.radar.getResolution(ProductType.VEL));
        // 如果要保存netcdf 则需要调用该方法 否则只用netcdf 的数据结构 以及cache
        cinradRadar.radar.flush();
        log.info(cinradRadar.radar.netcdf.getDetailInfo());
        // 必须调用该方法 否则nc tmp 文件一直保留
        cinradRadar.dispose();
        log.info("sum time : {}", System.currentTimeMillis() - time);
    }

    /**
     * 读取SC CD 波段雷达
     *
     * @throws RadarDecodeError
     * @throws IOException
     * @throws InvalidRangeException
     */
    @Test
    public void readSCCD() throws RadarDecodeError, IOException, InvalidRangeException {
        long time = System.currentTimeMillis();
        String file = "/Users/xx/data/micaps/SINGLERADAR/ARCHIVES/PRE_QC/Z9852/Z_RADR_I_Z9852_20190729235847_O_DOR_CD_CAP.bin.bz2";
//        String file = "/Users/xx/data/micaps/SINGLERADAR/ARCHIVES/PRE_QC/Z9280/Z_RADR_I_Z9280_20190730113200_O_DOR_SC_CAP.bin.bz2";
        CinradRadar cinradRadar = new CinradRadar();
        cinradRadar.parse(file);
        log.info("radar site : {}", cinradRadar.radar.getRadarSite().toString());
        log.info("radar station code : {}", cinradRadar.code);
        log.info("cinrad radar type : {}", cinradRadar.type.name());
        log.info("radar ref resolution : {}m", cinradRadar.radar.getResolution(ProductType.REF));
        log.info("radar vel resolution : {}m", cinradRadar.radar.getResolution(ProductType.VEL));
        // 如果要保存netcdf 则需要调用该方法 否则只用netcdf 的数据结构 以及cache
        cinradRadar.radar.flush();
        log.info(cinradRadar.radar.netcdf.getDetailInfo());
        // 必须调用该方法 否则nc tmp 文件一直保留
        cinradRadar.dispose();
        log.info("sum time : {}", System.currentTimeMillis() - time);
    }

    /**
     * 读取SC CD 波段雷达
     *
     * @throws RadarDecodeError
     * @throws IOException
     * @throws InvalidRangeException
     */
    @Test
    public void readCC() throws RadarDecodeError, IOException, InvalidRangeException, RadarVisualizeError, RadarCaclError {
        long time = System.currentTimeMillis();
        String file = "C:\\Users\\Administrator\\Desktop\\昆明航迹\\全省雷达基数据样本\\kidpl\\2021020800.33V";
        CinradRadar cinradRadar = new CinradRadar();
        cinradRadar.parse(file, CinradType.CC, "Z9872");
        log.info("radar site : {}", cinradRadar.radar.getRadarSite().toString());
        log.info("radar station code : {}", cinradRadar.code);
        log.info("cinrad radar type : {}", cinradRadar.type.name());
        log.info("radar ref resolution : {}m", cinradRadar.radar.getResolution(ProductType.REF));
        log.info("radar vel resolution : {}m", cinradRadar.radar.getResolution(ProductType.VEL));
        RasterMap rasterMap = new RasterMap(cinradRadar.radar);
        for (int i = 0; i < 11; i++) {
            RasterMap.RasterInfo rasterInfo = RasterMap.buildRasterInfo(ProductType.REF)
                    // 背景颜色
                    .backColor(Color.black)
                    // 是否显示右边详细信息 以及图例
                    .simpleDetail(true)
                    .drawCity(true)
                    // 是否画范围 不需要的话可以不调用该函数
                    .rings(new int[]{50, 100, 150, 200, 230, 400, 460});
            BufferedImage bufferedImage = rasterMap.simplePPI(rasterInfo, i);
//            BufferedImage bufferedImage = rasterMap.simpleCR(rasterInfo);
            ImageIO.write(bufferedImage, "png", new File(new File(file).getParentFile().getAbsolutePath() + File.separator + i + ".png"));
        }
        cinradRadar.dispose();
    }

    /**
     * 读取SC CD 波段雷达
     *
     * @throws RadarDecodeError
     * @throws IOException
     * @throws InvalidRangeException
     */
    @Test
    public void read784() throws RadarDecodeError, IOException, InvalidRangeException, RadarVisualizeError, RadarCaclError {
        long time = System.currentTimeMillis();
        String file = "E:\\data\\hmbdata\\KLG000130320190501020050012.PPI";
        CinradRadar cinradRadar = new CinradRadar();
        cinradRadar.parse(file, CinradType.SC, "Z9872");
//        log.info("radar site : {}", cinradRadar.radar.getRadarSite().toString());
//        log.info("radar station code : {}", cinradRadar.code);
//        log.info("cinrad radar type : {}", cinradRadar.type.name());
//        log.info("radar ref resolution : {}m", cinradRadar.radar.getResolution(ProductType.REF));
//        log.info("radar vel resolution : {}m", cinradRadar.radar.getResolution(ProductType.VEL));
        RasterMap rasterMap = new RasterMap(cinradRadar.radar);
        for (int i = 0; i < 11; i++) {
            RasterMap.RasterInfo rasterInfo = RasterMap.buildRasterInfo(ProductType.REF)
                    // 背景颜色
                    .backColor(Color.black)
                    // 是否显示右边详细信息 以及图例
                    .simpleDetail(true)
                    .drawCity(true)
                    // 是否画范围 不需要的话可以不调用该函数
                    .rings(new int[]{50, 100, 150, 200, 230, 400, 460});
            BufferedImage bufferedImage = rasterMap.simplePPI(rasterInfo, i);
            ImageIO.write(bufferedImage, "png", new File(new File(file).getParentFile().getAbsolutePath() + File.separator + i + ".png"));
        }
        cinradRadar.dispose();
    }

    /**
     * 读取 新一代天气雷达
     *
     * @throws RadarDecodeError
     * @throws IOException
     * @throws InvalidRangeException
     */
    @Test
    public void readStandard() throws RadarDecodeError, IOException, InvalidRangeException, RadarVisualizeError, RadarCaclError {
        long time = System.currentTimeMillis();
        String file = "/Users/xx/DeskTop/9692/Z_RADR_I_Z9692_20210119060342_O_DOR_CC_CAP_FMT.bin.bz2";
        CinradRadar cinradRadar = new CinradRadar();
        cinradRadar.parse(file);
        cinradRadar.radar.flush();
        log.info("radar site : {}", cinradRadar.radar.getRadarSite().toString());
        log.info("radar station code : {}", cinradRadar.code);
        log.info("cinrad radar type : {}", cinradRadar.type.name());
        log.info("radar ref resolution : {}m", cinradRadar.radar.getResolution(ProductType.REF));
        log.info("radar vel resolution : {}m", cinradRadar.radar.getResolution(ProductType.VEL));
        RasterMap rasterMap = new RasterMap(cinradRadar.radar);
//        for(int i = 0 ; i < 11 ; i ++){
        RasterMap.RasterInfo rasterInfo = RasterMap.buildRasterInfo(ProductType.REF)
                // 背景颜色
                .backColor(Color.black)
                // 是否显示右边详细信息 以及图例
                .simpleDetail(true)
                .drawCity(true)
                // 是否画范围 不需要的话可以不调用该函数
                .rings(new int[]{50, 100, 150, 200, 230, 400, 460});
        BufferedImage bufferedImage = rasterMap.simplePPI(rasterInfo, 0);
//            BufferedImage bufferedImage = rasterMap.simpleCR(rasterInfo);
        ImageIO.write(bufferedImage, "png", new File("/Users/xx/DeskTop/ppi.png"));
//        }
        cinradRadar.dispose();
//        // 如果要保存netcdf 则需要调用该方法 否则只用netcdf 的数据结构 以及cache
//        cinradRadar.radar.flush();
//        log.info(cinradRadar.radar.netcdf.getDetailInfo());
//        // 必须调用该方法 否则nc tmp 文件一直保留
//        cinradRadar.dispose();
//        log.info("sum time : {}", System.currentTimeMillis() - time);
    }

    /**
     * 读取 382
     *
     * @throws RadarDecodeError
     * @throws IOException
     * @throws InvalidRangeException
     */
    @Test
    public void read382() throws Exception {
        long time = System.currentTimeMillis();

        parse382(null, "LD20130425110954119.VT382", 0);
        parse382("LD20130425110954119.VT382", "LD20130425111445119.VT382", 5);
        parse382("LD20130425111445119.VT382", "LD20130425111802119.VT382", 5);
//        CinradRadar cinradRadar = new CinradRadar();
//        cinradRadar.parse("D:\\tmp\\LD20130425110954119.VT382", CinradType.RADAR382);
//
//        RadarGridData cr = cinradRadar.radar.getCR();
//        double[][] decode = MathCommon.decode(cr.radarData, ProductType.REF);
//
//        int step = 2;
//        double[][] data = new double[decode.length / step][decode[0].length / step];
//        for (int i = 0; i < data.length; i++) {
//            for (int j = 0; j < data[0].length; j++) {
//                data[i][j] = decode[i * step][j * step];
//            }
//        }
//        CinradRadar cinradRadar2 = new CinradRadar();
//        cinradRadar2.parse("D:\\tmp\\LD20130425111802119.VT382", CinradType.RADAR382);
//        cinradRadar.radar.flush();

//        byte[] bytes1 = FileUtil.readBytes("D:\\LD20130425110954119.VT382.dat");
//        byte[] bytes2 = FileUtil.readBytes("D:\\LD20130425111445119.VT382.dat");
//        byte[] bytes3 = FileUtil.readBytes("D:\\LD20130425111802119.VT382.dat");

//        double[][] Z1 = BitConverter.toDouble(bytes1, 500, 500);
//        double[][] Z2 = BitConverter.toDouble(bytes2, 500, 500);
//        double[][] Z3 = BitConverter.toDouble(bytes3, 500, 500);

//        RefObj<Integer> count1 = new RefObj<>(0);
//        List<Storms.StormDt> list = Storms.getStorms(data, step, count1, 28, cinradRadar);
//
//        RefObj<Integer> count2 = new RefObj<>(0);
//        List<Storms.StormDt> list1 = Storms.getStorms(Z2, 4, count2, 32, cinradRadar1);

//        Storms.track(list,list1,cinradRadar1);

//        RefObj<Integer> count3 = new RefObj<>(0);
//        List<Storms.StormDt> list2 = Storms.getStorms(Z3, 4, count3, 32, cinradRadar2);
//
//        Storms.track(list1,list2,cinradRadar2);

//        System.out.print(list2.size());

//        RasterMap rasterMap = new RasterMap(cinradRadar.radar);
//        BufferedImage bufferedImage = rasterMap.simpleRaster(RasterMap.buildRasterInfo(ProductType.REF), cr);
//
//        Graphics2D graphics = (Graphics2D) bufferedImage.getGraphics();
//        graphics.setColor(Color.RED);
//        list.stream().forEach(storm -> {
//            List<PointD> points = storm.getBoundary();
//            int[] x = new int[points.size()];
//            int[] y = new int[points.size()];
//            for (int i = 0; i < x.length; i++) {
//                x[i] = (int) points.get(i).X;
//                y[i] = (int) points.get(i).Y;
//            }
//            graphics.drawPolyline(y, x, points.size());
//        });
//        ImageIO.write(bufferedImage, "png", new File("D:\\tmp\\LD20130425110954119.VT382.png"));
//        cinradRadar.dispose();
        log.info("sum time : {}", System.currentTimeMillis() - time);
    }

    public void parse382(String pre, String next, int offset) throws Exception {
        String output = "D:\\tmp\\";
        String date = next.substring(2, 19);
        CinradRadar nextCinrad = new CinradRadar();
        nextCinrad.parse(output + next, CinradType.RADAR_382);
        // 生成CR
        RadarGridData cr = nextCinrad.radar.getCR();
        RasterMap rasterMap = new RasterMap(nextCinrad.radar);
        FileUtil.mkdir(output + date + File.separator);

        // draw cr
        BufferedImage bufferedImage = rasterMap.drawSingleRaster(MathCommon.decode(cr.radarData, ProductType.REF), ProductType.REF, new Color(0, 0, 0, 0));
        ImageIO.write(bufferedImage, "png", new File(output + date + File.separator + date + "_CR_0.png"));

        // draw gray
        double[][] gray = MathCommon.decode(cr.radarData, ProductType.REF);
        gray = Cacl.nineMedianFilter(gray);
        gray = Cacl.nineMedianFilter(gray);
        gray = Cacl.nineMedianFilter(gray);
        bufferedImage = rasterMap.drawSingleRaster(gray, ProductType.REFGRAY);
        ImageIO.write(bufferedImage, "png", new File(output + date + File.separator + "CR_GRAY.png"));

        // find pre GRAY
        if (pre != null) {
            forecast(output + pre.substring(2, 19) + File.separator + "CR_GRAY.png",
                    output + date + File.separator + "CR_GRAY.png",
                    offset, cr, nextCinrad, next);
        }
        // output storms
        RefObj<Integer> count1 = new RefObj<>(0);
        int step = 2;
        double[][] decode = MathCommon.decode(cr.radarData, ProductType.REF);
        double[][] data = new double[decode.length / step][decode[0].length / step];
        for (int i = 0; i < data.length; i++) {
            for (int j = 0; j < data[0].length; j++) {
                data[i][j] = decode[i * step][j * step];
            }
        }
        List<Storms.StormDt> list = Storms.getStorms(data, step, count1, 28, nextCinrad);
//        Gson gson = new Gson();
//        // 判断上一个json 是否存在
//        if (pre != null) {
//            CinradRadar preCinrad = new CinradRadar();
//            preCinrad.parse(output + pre, CinradType.RADAR_382);
//            double[][] decodePre = MathCommon.decode(preCinrad.radar.getCR().radarData, ProductType.REF);
//            double[][] dataPre = new double[decodePre.length / step][decodePre[0].length / step];
//            for (int i = 0; i < dataPre.length; i++) {
//                for (int j = 0; j < dataPre[0].length; j++) {
//                    dataPre[i][j] = decodePre[i * step][j * step];
//                }
//            }
//            RefObj<Integer> count = new RefObj<>(0);
//            List<Storms.StormDt> list0 = Storms.getStorms(dataPre, step, count, 28, preCinrad);
//            // 计算风暴外推
//            List<Storms.StormDt> track = Storms.track(list0, list, nextCinrad);
//            if (track != null) {
//                list = track;
//            }
//        }
//        list.forEach(z -> {
//            z.setCenter(new PointD(cr.xArray[(int) z.getCenter().Y], cr.yArray[cr.yArray.length - 1 - (int) z.getCenter().X]));
//            z.getBoundary().forEach(point -> {
//                double x = cr.xArray[(int) point.Y];
//                double y = cr.yArray[cr.yArray.length - 1 - (int) point.X];
//                point.X = x;
//                point.Y = y;
//            });
//            z.getContain().forEach(point -> {
//                double x = cr.xArray[(int) point.Y];
//                double y = cr.yArray[cr.yArray.length - 1 - (int) point.X];
//                point.X = x;
//                point.Y = y;
//            });
//        });
//        FileUtil.writeString(gson.toJson(list), new File(output + date + File.separator + date + "_strom.json"), Charset.defaultCharset());
//        FileUtil.writeString(cr.getXMin() + ";" + cr.getXMax() + ";" + cr.getYMin() + ";" + cr.getYMax(), new File(output + date + File.separator + date + "_extent.json"), Charset.defaultCharset());
//        nextCinrad.radar.flush();
    }

    /**
     * 读取 720
     *
     * @throws RadarDecodeError
     * @throws IOException
     * @throws InvalidRangeException
     */
    @Test
    public void read720() throws RadarDecodeError, RadarVisualizeError, RadarCaclError, IOException, InvalidRangeException {
        String file = "/Users/xx/data/渤海湾/雷达/suizhong/PTB20210509191337.002";
        CinradRadar radar = new CinradRadar();
        radar.parse(file, CinradType.RADAR_720);
        RasterMap rasterMap = new RasterMap(radar.radar);
        BufferedImage bufferedImage = rasterMap.simplePPI(RasterMap.
                buildRasterInfo(ProductType.REF)
                .backColor(new Color(0, 0, 0, 0)),0);
        ImageIO.write(bufferedImage, "png", new File("/Users/xx/data/渤海湾/雷达/suizhong/test.png"));
    }

    /**
     * 读取 锦江电子06CDN
     *
     * @throws RadarDecodeError
     * @throws IOException
     * @throws InvalidRangeException
     */
    @Test
    public void read06CDN() throws RadarDecodeError, RadarVisualizeError, RadarCaclError, IOException, InvalidRangeException {
        String file = "/Users/xx/data/渤海湾/雷达/nanshan/2021031207590.05P";
        CinradRadar radar = new CinradRadar();
        radar.parse(file, CinradType.RADAR_06CDN);
        RasterMap rasterMap = new RasterMap(radar.radar);
        BufferedImage bufferedImage = rasterMap.simplePPI(RasterMap.
                buildRasterInfo(ProductType.REF)
                .backColor(new Color(0, 0, 0, 0)),0);
        ImageIO.write(bufferedImage, "png", new File("/Users/xx/data/渤海湾/雷达/nanshan/test.png"));
        radar.radar.flush();
    }

    /**
     * 读取 锦江电子721
     *
     * @throws RadarDecodeError
     * @throws IOException
     * @throws InvalidRangeException
     */
    @Test
    public void read721() throws RadarDecodeError, RadarVisualizeError, RadarCaclError, IOException, InvalidRangeException {
        String file = "/Users/xx/data/渤海湾/雷达/shanhaiguan/2021050919340.15P";
        CinradRadar radar = new CinradRadar();
        radar.parse(file, CinradType.RADAR_721);
        RasterMap rasterMap = new RasterMap(radar.radar);
        BufferedImage bufferedImage = rasterMap.simplePPI(RasterMap.
                buildRasterInfo(ProductType.REF)
                .backColor(new Color(0, 0, 0, 0)),0);
        ImageIO.write(bufferedImage, "png", new File("/Users/xx/data/渤海湾/雷达/shanhaiguan/test.png"));
        radar.radar.flush();
    }

    public void forecast(String preImg, String nextImg, int offset, RadarGridData cr, CinradRadar cinradRadar, String filename) throws IOException {
        String output = "D:\\tmp\\";
        String date = filename.substring(2, 19);
        Mat ff1 = opencv_imgcodecs.imread(preImg);
        Mat ff2 = opencv_imgcodecs.imread(nextImg);
        Mat prvs = ff1.clone();
        Mat next = ff1.clone();
        opencv_imgproc.cvtColor(ff1, prvs, opencv_imgproc.COLOR_BGR2GRAY);
        opencv_imgproc.cvtColor(ff2, next, opencv_imgproc.COLOR_BGR2GRAY);

        int w = prvs.size().get(0);
        int h = prvs.size().get(1);
        double[][] pre = new double[h][w];
        double[][] nex = new double[h][w];
        Indexer indexer = prvs.createIndexer();
        Indexer indexer1 = next.createIndexer();
        for (int i = 0; i < h; i++) {
            for (int j = 0; j < w; j++) {
                pre[i][j] = indexer.getDouble(i, j);
                if (pre[i][j] == 255) {
                    pre[i][j] = 0;
                }
                nex[i][j] = indexer1.getDouble(i, j);
                if (nex[i][j] == 255) {
                    nex[i][j] = 0;
                }
            }
        }
        double[][][] cacl = DenseLucaskanade.cacl(new double[][][]{pre, nex});
        double[][] u = cacl[0];
        double[][] v = cacl[1];
        for (int i = 0; i < h; i++) {
            for (int j = 0; j < w; j++) {
                u[i][j] = u[i][j] * (3.0 / offset);
                v[i][j] = v[i][j] * (3.0 / offset);
            }
        }
        double[][] decode = MathCommon.decode(cr.radarData, ProductType.REF);
        if (decode.length == u.length && decode[0].length == u[0].length) {

        } else {
            double[][] z = new double[u.length][u[0].length];
            for (int i = 0; i < h; i++) {
                for (int j = 0; j < w; j++) {
                    if (i >= decode.length || j >= decode[0].length) {
                        z[i][j] = GisConstants.UNDEF;
                    } else {
                        z[i][j] = decode[i][j];
                    }
                }
            }
            decode = z;
        }

        SemiLagrangian semiLagrangian = new SemiLagrangian();
        int t = 20;
        float[][][] extrapolate = semiLagrangian.extrapolate(MathCommon.doubleToFloat(decode), MathCommon.doubleToFloat(u), MathCommon.doubleToFloat(v), t);
        cinradRadar.radar.writeSemiLagrangian(extrapolate, 5, t);
        for (int i = 0; i < t; i++) {
            BufferedImage bufferedImage;
            for (int j = 0; j < u.length; j++) {
                for (int k = 0; k < u[0].length; k++) {
                    extrapolate[i][j][k] = extrapolate[i][j][k] == 0 || extrapolate[i][j][k] == Float.NaN ? GisConstants.UNDEF : extrapolate[i][j][k];
                }
            }
            RasterMap rasterMap = new RasterMap(cinradRadar.radar);
            bufferedImage = rasterMap.drawSingleRaster(MathCommon.floatToDouble(extrapolate[i]), new Color(0, 0, 0, 0));
            ImageIO.write(bufferedImage, "png", new File(output + date + File.separator + date + "_CR_" + (i + 1) + ".png"));
        }

    }

    /**
     * 云南数据测试
     */
    @Test
    public void readOtherType() throws RadarDecodeError, RadarCaclError, InvalidRangeException, IOException, RadarVisualizeError {
        long time = System.currentTimeMillis();
        File file = new File("/Users/xx/data/昆明航迹/radar/ztdpl/2020102112.24V");
        CinradRadar cinradRadar = new CinradRadar();
        cinradRadar.setCode("Z9870");
        cinradRadar.parse(file.getAbsolutePath(), CinradType.CC);
        BufferedImage bufferedImage = new RasterMap(cinradRadar.radar).simpleCR(RasterMap.buildRasterInfo(ProductType.CR));
        ImageIO.write(bufferedImage, "png", new File(file.getParentFile().getAbsolutePath() + File.separator + "CR.png"));
        cinradRadar.radar.flush();
        cinradRadar.radar.close();
        System.out.println(System.currentTimeMillis() - time);
    }

    /**
     * 输出netcdf
     */
    @Test
    public void toNetCDF() throws RadarDecodeError, RadarCaclError, InvalidRangeException, IOException {
        long time = System.currentTimeMillis();
            String file = "/Users/xx/data/micaps/SINGLERADAR/ARCHIVES/PRE_QC/Z9092/Z_RADR_I_Z9092_20190729220800_O_DOR_SA_CAP.bin.bz2";
        CinradRadar cinradRadar = new CinradRadar();
        cinradRadar.parse(file);
        // 计算产品之后 会自动写到netcdf 里
        cinradRadar.radar.getCR();
        // 如果要保存netcdf 则需要调用该方法 否则只用netcdf 的数据结构 以及cache
        cinradRadar.radar.flush();
        File f = cinradRadar.radar.getNetCDF();
        log.info("netcdf path : {} you can copy that", f.getAbsolutePath());
        log.info(cinradRadar.radar.netcdf.getDetailInfo());
        // 必须调用该方法 否则nc tmp 文件一直保留
        cinradRadar.dispose();
        log.info("sum time : {}", System.currentTimeMillis() - time);
    }

    /**
     * 获取极坐标数据
     *
     * @throws RadarCaclError
     * @throws RadarDecodeError
     */
    @Test
    public void readPolar() throws RadarCaclError, RadarDecodeError, IOException, InvalidRangeException {
        long time = System.currentTimeMillis();
        String file = "/Users/xx/data/micaps/SINGLERADAR/ARCHIVES/PRE_QC/Z9092/Z_RADR_I_Z9092_20190729220800_O_DOR_SA_CAP.bin.bz2";
        CinradRadar cinradRadar = new CinradRadar();
        cinradRadar.parse(file);
        // 仰角层索引
        int layerIndex = 0;
        // 基本数据类型 REF VEL SW RF ZDR ...
        ProductType type = ProductType.REF;
        // 直接读取极坐标数据 速度很快
        byte[][] raw = cinradRadar.radar.getRaw(layerIndex, type);
        log.info("ref raw length : {} , {}", raw.length, raw[0].length);
        double[] azi = cinradRadar.radar.getAzimuth()[layerIndex];
        log.info("Azimuth length : {}", azi.length);
        RefObj<double[]> newazi = new RefObj<>(null);
        RefObj<byte[][]> newz = new RefObj<>(null);
        // 根据 方位角从小到大排序
        Cacl.sortAzi(azi, raw, newazi, newz);
        log.info("sum time : {}", System.currentTimeMillis() - time);
        cinradRadar.radar.flush();
        log.info(cinradRadar.radar.netcdf.getDetailInfo());
        cinradRadar.radar.dispose();
    }

    /**
     * 计算二次产品 cr et vil
     *
     * @throws RadarDecodeError
     * @throws RadarCaclError
     * @throws InvalidRangeException
     * @throws IOException
     * @throws RadarVisualizeError
     */
    @Test
    public void productCacl() throws RadarDecodeError, RadarCaclError, InvalidRangeException, IOException, RadarVisualizeError {
        long time = System.currentTimeMillis();
        String file = "/Users/xx/data/micaps/SINGLERADAR/ARCHIVES/PRE_QC/Z9092/Z_RADR_I_Z9092_20190729220800_O_DOR_SA_CAP.bin.bz2";
        CinradRadar cinradRadar = new CinradRadar();
        cinradRadar.parse(file);
        // 计算产品等方法结果集存为lonlat 投影
        RadarGridData cr = cinradRadar.radar.getCR();
        log.info("cacl CR time : {}", System.currentTimeMillis() - time);
        // raster map
        RasterMap rasterMap = new RasterMap(cinradRadar.radar);
        RasterMap.RasterInfo rasterInfo = RasterMap.buildRasterInfo(ProductType.REF)
                .backColor(Color.black)
                .drawCity(true)
                .simpleDetail(true)
                .rings(new int[]{50, 100, 150, 200, 230, 300, 400, 460});
        BufferedImage bufferedImage = rasterMap.simpleRaster(rasterInfo, cr);
        ImageIO.write(bufferedImage, "png", new File("/Users/xx/DeskTop/CR.png"));

        time = System.currentTimeMillis();
        RadarGridData et = cinradRadar.radar.getET();
        log.info("cacl ET time : {}", System.currentTimeMillis() - time);
        rasterInfo.type(ProductType.ET);
        bufferedImage = rasterMap.simpleRaster(rasterInfo, et);
        ImageIO.write(bufferedImage, "png", new File("/Users/xx/DeskTop/ET.png"));

        time = System.currentTimeMillis();
        RadarGridData vil = cinradRadar.radar.getVIL();
        log.info("cacl VIL time : {}", System.currentTimeMillis() - time);
        rasterInfo.type(ProductType.VIL);
        bufferedImage = rasterMap.simpleRaster(rasterInfo, vil);
        ImageIO.write(bufferedImage, "png", new File("/Users/xx/DeskTop/VIL.png"));
    }

    @Test
    public void ppi() throws RadarDecodeError, RadarCaclError, InvalidRangeException, IOException {
        long time = System.currentTimeMillis();
        String file = "/Users/xx/data/micaps/SINGLERADAR/ARCHIVES/PRE_QC/Z9092/Z_RADR_I_Z9092_20190729220800_O_DOR_SA_CAP.bin.bz2";
        CinradRadar cinradRadar = new CinradRadar();
        cinradRadar.parse(file);
        // 仰角层索引
        int layerIndex = 0;
        // 基本数据类型 REF VEL SW RF ZDR ...
        ProductType type = ProductType.REF;
        // 投影到等经纬度 ppi 并计算仰角
        GridData ppi = cinradRadar.radar.getPPI(layerIndex, type);
        cinradRadar.radar.flush();
        log.info(cinradRadar.radar.netcdf.getDetailInfo());
        cinradRadar.radar.dispose();
        log.info("sum time : {}", System.currentTimeMillis() - time);
    }

    public static void main(String[] args) throws RadarDecodeError, RadarVisualizeError, RadarCaclError, IOException, InvalidRangeException {
        FileUtil.del("/Users/xx/Desktop/Z_RADR_I_Z9734_20210114005400_O_DOR_SA_CAP.bin.bz2.nc");
        String file = "/Users/xx/Desktop/Z_RADR_I_Z9734_20210114005400_O_DOR_SA_CAP.bin.bz2";
        CinradRadar cinradRadar = new CinradRadar();
        cinradRadar.parse(file);
        long time = System.currentTimeMillis();
        long time1 = System.currentTimeMillis();
        RadarGridData cr = cinradRadar.radar.getCR();
        RadarGridData et = cinradRadar.radar.getET();
        RadarGridData vil = cinradRadar.radar.getVIL();
        log.info("cr end : {}", System.currentTimeMillis() - time);
        time = System.currentTimeMillis();
//        RadarGridData et = cinradRadar.radar.getET();
//        log.info("et end : {}",System.currentTimeMillis() - time);
//        time = System.currentTimeMillis();
//        RasterMap rasterMap = new RasterMap(cinradRadar.radar);
//        PolarMap polarMap = new PolarMap(cinradRadar.radar);
//        RasterMap.RasterInfo rasterInfo = RasterMap.buildRasterInfo(ProductType.REF)
//                // 背景颜色
//                .backColor(new Color(0, 0, 0, 0))
//                .drawCity(false)
//                .simpleDetail(false);
//        BufferedImage bufferedImage = rasterMap.drawSingleRaster(cr.data);
//        ImageIO.write(bufferedImage, "png", new File("/Users/xx/DeskTop/CR.png"));
//        bufferedImage = rasterMap.drawSingleRaster(et.data, ProductType.ET, new Color(0, 0, 0, 0));
//        ImageIO.write(bufferedImage, "png", new File("/Users/xx/DeskTop/ET.png"));
//        for (int i = 0; i < cinradRadar.radar.getElevation().length; i++) {
//            bufferedImage = polarMap.simplePolar(PolarMap.
//                    buildPolarInfo(i, ProductType.REF)
//                    .backColor(new Color(0, 0, 0, 0)));
//            ImageIO.write(bufferedImage, "png", new File("/Users/xx/DeskTop/PPI_"+i+".png"));
//        }
        log.info("ppi end : {}", System.currentTimeMillis() - time);
        cinradRadar.radar.flush();
        log.info("draw end : {}", System.currentTimeMillis() - time1);
    }

    public static Extent getExtent(ProductType type, CinradRadar cinradRadar, int index) throws RadarCaclError, RadarDecodeError, IOException, InvalidRangeException {
        Extent extent = null;
        double lon = cinradRadar.radar.getRadarSite().getLon();
        double lat = cinradRadar.radar.getRadarSite().getLat();
        if (type == ProductType.REF || type == ProductType.VEL) {
            double res = cinradRadar.radar.getResolution(type);
            byte[][] raw = cinradRadar.radar.getRaw(index, type);
            double ele = cinradRadar.radar.getElevation()[index];
            double distance = raw[0].length * res;
            distance = Math.cos(ele * Const.DEG2RAD) * distance;
            extent = Common.getExtentRadius(lon, lat, distance);
        } else if (type == ProductType.CR) {
            extent = cinradRadar.radar.getCR().getExtent();
        } else if (type == ProductType.ET) {
            extent = cinradRadar.radar.getET().getExtent();
        } else if (type == ProductType.VIL) {
            extent = cinradRadar.radar.getVIL().getExtent();
        }
        return extent;
    }
}
